package com.yanqu.road.ak13;

import java.util.List;

import com.yanqu.road.define.YanQuOPCDefine;
import com.yanqu.road.define.YanQuMessageDefine;
import com.yanqu.road.message.YanQuMessage;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.http.websocketx.WebSocketFrameEncoder;

public class YanQuWSEncrypt0 extends MessageToMessageEncoder<YanQuMessage> implements WebSocketFrameEncoder {

	private static final ByteBuf _0XFF_0X00 = Unpooled.unreleasableBuffer(Unpooled.directBuffer(2, 2).writeByte((byte) 0xFF).writeByte((byte) 0x00));

	protected void encode(ByteBuf buf, List<Object> out, ByteBuf data) {
		buf.writeByte((byte) 0x80);

		int dataLen = data.readableBytes();

		int b1 = dataLen >>> 28 & 0x7F;
		int b2 = dataLen >>> 14 & 0x7F;
		int b3 = dataLen >>> 7 & 0x7F;
		int b4 = dataLen & 0x7F;
		if (b1 == 0) {
			if (b2 == 0) {
				if (b3 == 0) {
					buf.writeByte(b4);
				} else {
					buf.writeByte(b3 | 0x80);
					buf.writeByte(b4);
				}
			} else {
				buf.writeByte(b2 | 0x80);
				buf.writeByte(b3 | 0x80);
				buf.writeByte(b4);
			}
		} else {
			buf.writeByte(b1 | 0x80);
			buf.writeByte(b2 | 0x80);
			buf.writeByte(b3 | 0x80);
			buf.writeByte(b4);
		}

		out.add(buf);
		out.add(data.retain());

	}

	@Override
	protected void encode(ChannelHandlerContext ctx, YanQuMessage msg, List<Object> out) throws Exception {
		if (msg.getOpCode() == YanQuOPCDefine.OPCODE_CLOSE) {
			out.add(_0XFF_0X00.duplicate());
		}

		else {
			int dataSize = YanQuMessageDefine.HEADER_SIZE;
			if (msg.getBytes() != null) {
				dataSize += msg.getBytes().length;
			}

			final ByteBuf data = ctx.alloc().buffer(dataSize);
			msg.writeHeaderByte(dataSize, data);
			ByteBuf buf = ctx.alloc().buffer(5);
			boolean release = true;

			try {
				encode(buf, out, data);
				release = false;
			} finally {
				if (release) {
					buf.release();
				}
			}
		}
	}
}
